
#include "event/Event.h"
#include "functor/SubscriberSlot.h"
#include "event/BoundSlot.h"
#include <algorithm>
namespace KCore
{
	class SubComp
	{
	public:
		  SubComp(const BoundSlot& s) :_s(s)
		  {}

		  bool operator()(std::pair<int, Connection> e) const
		  {
			  return *(e.second) == _s;
		  }

	private:
		void operator=(const SubComp&) {}
		const BoundSlot& _s;
	};

	//-------------------------------------------------------------------
	Event::Event(const EventID id) :
	_id(id),_name("unname")
	{

	}


	Event::Event(const std::string& name):
	_name(name),_id(0)
	{
		
	}

	Event::~Event()
	{
		SlotContainer::iterator iter(_slots.begin());
		const SlotContainer::const_iterator end_iter(_slots.end());

		for (; iter != end_iter; ++iter)
		{
			iter->second->_event = 0;
			iter->second->_subscriber->cleanup();
		}
		_slots.clear();
	}

	Connection Event::subscribe(const Subscriber& slot)
	{
		return subscribe(static_cast<int>(10), slot);
	}

	Connection Event::subscribe(int group, const Subscriber& slot)
	{
		Connection c(new BoundSlot(group, slot, *this));
		_slots.insert(std::pair<int, Connection>(group, c));
		return c;
	}

	
	int Event::operator()(EventArgs* args)
	{
		SlotContainer::iterator iter(_slots.begin());
		const SlotContainer::const_iterator end_iter(_slots.end());

		for (; iter != end_iter; ++iter)
			if ((*iter->second->_subscriber)(args)==0)
			{
				if(args)
				++(args->handled);	
			}

		return _slots.size();
	}

	
	void Event::unsubscribe(const BoundSlot& slot)
	{
		// try to find the slot in our collection
		SlotContainer::iterator curr =
			std::find_if(_slots.begin(),
			_slots.end(),
			SubComp(slot));

		// erase our reference to the slot, if we had one.
		if (curr != _slots.end())
			_slots.erase(curr);
	}


};
